#pragma once
#include <queue>
#include "Mutex.hpp"
#include "Thread.hpp"
#include "Cond.hpp"
namespace BlockQueueMoudle
{
    using namespace ThreadMoudle;
    const int gcap = 10;

    // // v2
        class Blockqueue
    {

    private:
        bool IsFull() { return _cap == _q.size(); }
        bool IsEmpty() { return _q.empty(); }

    public:
        Blockqueue(int cap = gcap)
            : _cap(cap),_p_cond(_mutex.Mutex_ptr()),_c_cond(_mutex.Mutex_ptr())
        {

        }
        ~Blockqueue()
        {
           
        }
        void Pop(int *out)
        {
            LockGuard lockguard(_mutex);

            //循环判断，防止其他消费者在IsEmpty时进入
            while (IsEmpty())
            {
                printf("消费者等待中...\n");
                _cwait_num++;
                _c_cond.Wait();
                _cwait_num--;
            }

            *out = _q.front();
            _q.pop();
            printf("Pop:%d\n", *out);

            //如果有生产者在等待，唤醒
            if(_pwait_num)
            _p_cond.Signal();
        }

        void Equeue(int &in)
        {
            LockGuard lockguard(_mutex);
            while (IsFull())
            {
                _pwait_num++;
                _p_cond.Wait();
                _pwait_num--;

            }

            _q.push(in);
            printf("Equeue: %d\n", in);

            //如果有消费者在等待，唤醒
            if(_cwait_num)
            _c_cond.Signal();
        }

    private:
        int _cap;
        std::queue<int> _q; // 临界资源
        Mutex _mutex;
        Cond _p_cond; // 生产者条件
        Cond _c_cond; // 消费者条件

        int _cwait_num;
        int _pwait_num;
    };

    // // v1
    // class Blockqueue
    // {

    // private:
    //     bool IsFull() { return _cap == _q.size(); }
    //     bool IsEmpty() { return _q.empty(); }

    // public:
    //     Blockqueue(int cap = gcap)
    //         : _cap(cap),_p_cond(PTHREAD_COND_INITIALIZER),_c_cond(PTHREAD_COND_INITIALIZER)
    //     {

    //     }
    //     ~Blockqueue()
    //     {
    //         pthread_cond_destroy(&_p_cond);
    //         pthread_cond_destroy(&_c_cond);
    //     }
    //     void Pop(int *out)
    //     {
    //         LockGuard lockguard(_mutex);

    //         //循环判断，防止其他消费者在IsEmpty时进入
    //         while (IsEmpty())
    //         {
    //             printf("消费者等待中...\n");
    //             _cwait_num++;
    //             pthread_cond_wait(&_c_cond, _mutex.Mutex_ptr());
    //             _cwait_num--;
    //         }

    //         *out = _q.front();
    //         _q.pop();
    //         printf("Pop:%d\n", *out);

    //         //如果有生产者在等待，唤醒
    //         if(_pwait_num)
    //         pthread_cond_signal(&_p_cond);
    //     }

    //     void Equeue(int &in)
    //     {
    //         LockGuard lockguard(_mutex);
    //         while (IsFull())
    //         {
    //             _pwait_num++;
    //             pthread_cond_wait(&_p_cond, _mutex.Mutex_ptr());
    //             _pwait_num--;

    //         }

    //         _q.push(in);
    //         printf("Equeue: %d\n", in);

    //         //如果有消费者在等待，唤醒
    //         if(_cwait_num)
    //         pthread_cond_signal(&_c_cond);
    //     }

    // private:
    //     int _cap;
    //     std::queue<int> _q; // 临界资源
    //     Mutex _mutex;
    //     pthread_cond_t _p_cond; // 生产者条件
    //     pthread_cond_t _c_cond; // 消费者条件

    //     int _cwait_num;
    //     int _pwait_num;
    // };

}